package com.xbongbong.workflow.service.strategy.node;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.ProcessEmptyApproverTypeEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.exception.WorkflowException;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.WorkflowHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.service.WorkflowApprovalOperate;
import com.xbongbong.pro.service.dingtalk.WorkflowDingtalkService;
import com.xbongbong.paas.service.dingtalkTodo.WorkflowDingtalkTodoService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.WorkflowTaskUtil;
import com.xbongbong.paas.util.WorkflowUtil;
import com.xbongbong.parent.help.PushMessageHelp;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.message.constant.ProcessPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.process.pojo.dto.WorkrecordInstanceDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.bo.WorkflowNoApproverBo;
import com.xbongbong.workflow.pojo.nodes.ApprovalNode;
import com.xbongbong.workflow.pojo.nodes.WorkflowTitlePojo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.common.util.set.Sets;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 工作流审批相关父类
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class AbstractWorkflowApprovalStrategy extends AbstractWorkflowNodeStrategy implements WorkflowApprovalStrategy{

    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private WorkflowDingtalkTodoService workflowDingtalkTodoService;
    @Resource
    private WorkflowDingtalkService workflowDingtalkService;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PushMessageHelp pushMessageHelp;
    @Resource
    private WorkflowHelp workflowHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private MessageService messageService;
    @Resource
    private WorkflowApprovalOperate workflowApprovalOperate;
    @Resource
    private FormDataHelp formDataHelp;

    @Override
    public WorkflowNoApproverBo createTaskNode(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, Long lastNodeId) throws WorkflowException {
        WorkflowNoApproverBo workflowNoApproverBo = new WorkflowNoApproverBo();
        workflowNoApproverBo.setAutoPaas(1);
        return workflowNoApproverBo;
    }

    @Override
    public String type() {
        return null;
    }

    @Override
    public void logger(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, WorkflowTaskLogStatusEnum workflowTaskLogStatusEnum, WorkflowException workflowException) {
        super.logger(workflowTransferPOJO, nodeEntity, workflowTaskLogStatusEnum, workflowException);
    }

    /**
     * Description: 创建审批节点
     * @param userIds 节点的审批人
     * @param workflowTransferPOJO 流转的数据实体
     * @param workflowNodeEntity 当前节点
     * @param lastNodeId 前一个节点的id
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2021/5/18 16:33
     * @since
     */
    protected void createApprovalNode(Collection<String> userIds, WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity, Long lastNodeId, TaskTypeEnum taskTypeEnum) throws WorkflowException {

        try {
            if (CollectionsUtil.isEmpty(userIds)) {
                return;
            }
            long now = DateTimeUtil.getInt();
            List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList = new ArrayList<>();
            for (String userId : userIds) {
                // 审批节点
                WorkflowTaskNodeEntity workflowTaskNodeEntity = new WorkflowTaskNodeEntity();
                workflowTaskNodeEntity.setCorpid(workflowNodeEntity.getCorpid());
                workflowTaskNodeEntity.setAppId(workflowNodeEntity.getAppId());
                workflowTaskNodeEntity.setFormId(workflowNodeEntity.getFormId());
                workflowTaskNodeEntity.setMenuId(workflowNodeEntity.getMenuId());
                workflowTaskNodeEntity.setSaasMark(workflowNodeEntity.getSaasMark());
                workflowTaskNodeEntity.setBusinessType(workflowNodeEntity.getBusinessType());
                workflowTaskNodeEntity.setWorkflowId(workflowNodeEntity.getWorkflowId());
                workflowTaskNodeEntity.setTaskId(workflowTransferPOJO.getTaskId());

                workflowTaskNodeEntity.setUserId(userId);
                workflowTaskNodeEntity.setDataId(workflowTransferPOJO.getData().getId());
                ApprovalNode approvalNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ApprovalNode.class);
                workflowTaskNodeEntity.setTaskType(taskTypeEnum.getType());
                workflowTaskNodeEntity.setSignType(approvalNode.getSignType() == null ? 1 : approvalNode.getSignType());
                workflowTaskNodeEntity.setNodeType(workflowNodeEntity.getType());
                workflowTaskNodeEntity.setLastNodeId(lastNodeId);
                workflowTaskNodeEntity.setWorkflowNodeId(workflowNodeEntity.getId());
                workflowTaskNodeEntity.setOpinion("");
                workflowTaskNodeEntity.setImages("");
                workflowTaskNodeEntity.setAttachment("");
                workflowTaskNodeEntity.setTransferUserId("");
                workflowTaskNodeEntity.setRevokeUserId("");
                workflowTaskNodeEntity.setBackspaceNode(0L);
                workflowTaskNodeEntity.setIsRead(0);
                workflowTaskNodeEntity.setAddTime(now);
                workflowTaskNodeEntity.setUpdateTime(now);
                workflowTaskNodeEntity.setDel(DelEnum.NORMAL.getDel());
                // serialno
                workflowTaskNodeEntity.setSerialNo(workflowTransferPOJO.getData().getData().getString("serialNo") == null ? "" : workflowTransferPOJO.getData().getData().getString("serialNo"));
                // 标题
                Set<Long> workOrder = new HashSet<>();
                Set<Long> others = new HashSet<>();
                Set<Long> workflowNodeIdSet = new HashSet<>();
                List<WorkflowTitlePojo> titles = approvalNode.getTitle();
                // 标题
                WorkflowUtil.getFormIdByTitle(titles, workOrder, others, workflowNodeIdSet);
                //工单的解释
                Map<Long, Map<String, FieldAttrEntity>> workOrderFormExplainMap = proFormHelp.getWorkOrderFormFieldMap(workOrder, workflowNodeEntity.getCorpid());
                //其他表单的解释
                Map<Long, Map<String, FieldAttrEntity>> formExplainMap = proFormHelp.getFormFieldMap(others, workflowNodeEntity.getCorpid());
                // 获取节点数据
                Map<Long, List<PaasFormDataEntityExt>> workflowNodeDataMap = workflowHelp.getWorkflowNodeDataMap(workflowNodeIdSet, workflowTransferPOJO);
                String title;
                //拼接标题
                if (CollectionUtils.isEmpty(titles)) {
                    title = workflowHelp.getDefaultTitle(workflowTransferPOJO);
                } else {
                    title = workflowHelp.getTitleValue(titles, formExplainMap, workOrderFormExplainMap, workflowTransferPOJO, workflowNodeDataMap, 50);
                }

                workflowTaskNodeEntity.setTitle(title);

                workflowTaskNodeEntityList.add(workflowTaskNodeEntity);

            }
            if (!workflowTaskNodeEntityList.isEmpty()) {
                workflowTaskNodeModel.insertBatch(workflowTaskNodeEntityList);

                //创建钉钉待办任务,只需要生成要审批的人的待办
                Runnable runnable = () -> {
                    try {
                        if (Objects.equals(taskTypeEnum, TaskTypeEnum.UNTREATED)) {
                            // 钉钉待办
                            createDingtalkTodoTask(workflowTaskNodeEntityList);
                        }
                        // 推送消息
                        if (Objects.equals(taskTypeEnum, TaskTypeEnum.UNTREATED) || Objects.equals(taskTypeEnum, TaskTypeEnum.CC)) {
                            PushRefTypePojo.Options options;
                            MessageRabbitMqDTO messageRabbitMqDTO;

                            String formName;
                            if (Objects.equals(workflowNodeEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                                WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
                                formName = workOrderFormEntityExt.getName();
                            } else {
                                PaasFormEntity paasFormEntity = paasFormModel.getByKey(workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
                                formName = paasFormEntity.getName();
                            }

                            JSONObject dataJson = workflowTransferPOJO.getData().getData();
                            PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
                            paasProcessDataEntity.setAppId(workflowNodeEntity.getAppId());
                            paasProcessDataEntity.setFormId(workflowNodeEntity.getFormId());
                            paasProcessDataEntity.setMenuId(workflowNodeEntity.getMenuId());
                            paasProcessDataEntity.setCorpid(workflowNodeEntity.getCorpid());
                            paasProcessDataEntity.setId(workflowTransferPOJO.getData().getId());
                            paasProcessDataEntity.setFormDataId(workflowTransferPOJO.getData().getId());
                            paasProcessDataEntity.setSaasMark(workflowNodeEntity.getSaasMark());
                            paasProcessDataEntity.setBusinessType(workflowNodeEntity.getBusinessType());
                            paasProcessDataEntity.setData(dataJson.toJSONString());
                            paasProcessDataEntity.setSerialNo(dataJson.getString(FieldTypeEnum.SERIALNO.getAlias()));
                            paasProcessDataEntity.setOwnerId(dataJson.getString(FieldTypeEnum.OWNERID.getAlias()));
                            paasProcessDataEntity.setAddTime(dataJson.getLong(FieldTypeEnum.ADDTIME.getAlias()));
                            paasProcessDataEntity.setUpdateTime(dataJson.getLong(FieldTypeEnum.UPDATETIME.getAlias()));

                            // 获取用户容器
                            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            param.put("corpid", workflowNodeEntity.getCorpid());
                            param.put("del", 0);
                            List<UserEntity> userList = userModel.findEntitys(param);
                            if (userList == null) {
                                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
                            }
                            Map<String, UserEntity> userMap = new HashMap<>(userList.size());
                            userList.forEach((item) -> userMap.put(item.getUserId(), item));
                            // 获取部门容器
                            param.remove(ParameterConstant.COLUMNS);
                            List<DepartmentEntity> departmentList = departmentModel.findEntitys(param);
                            if (departmentList == null) {
                                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
                            }
                            Map<String, DepartmentEntity> departmentMap = new HashMap<>(departmentList.size());
                            departmentList.forEach((departmentItem) -> departmentMap.put(departmentItem.getId().toString(), departmentItem));

                            BaseDTO baseDTO = new BaseDTO();
                            baseDTO.setCorpid(workflowNodeEntity.getCorpid());
                            String content = pushMessageHelp.getMessageContent(paasProcessDataEntity, userMap, departmentMap, baseDTO);

                            for (WorkflowTaskNodeEntity workflowTaskNodeEntity : workflowTaskNodeEntityList) {
                                if (Objects.equals(taskTypeEnum, TaskTypeEnum.UNTREATED)) {
                                    options = new PushRefTypePojo.Options(workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getFormId(),
                                            Collections.singletonList(workflowTransferPOJO.getData().getId()), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(),
                                            workflowTransferPOJO.getTaskId(), workflowTaskNodeEntity.getId(), ProcessTypeEnum.TODO.getValue());
                                    messageRabbitMqDTO = new MessageRabbitMqDTO(workflowNodeEntity.getCorpid(), Collections.singletonList(workflowTaskNodeEntity.getUserId()), Collections.singletonList(workflowTaskNodeEntity.getTaskId()), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_NODE_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_ADD_CONTENT), workflowTransferPOJO.getUser().getName(), formName, content), null, options);
                                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.APPROVAL_NODE_CHANGE_PUSH);
                                } else if (Objects.equals(taskTypeEnum, TaskTypeEnum.CC)) {
                                    options = new PushRefTypePojo.Options(workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getFormId(), Collections.singletonList(workflowTransferPOJO.getData().getId()), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(), workflowTransferPOJO.getTaskId(), workflowTaskNodeEntity.getId(), ProcessTypeEnum.CC.getValue());
                                    messageRabbitMqDTO = new MessageRabbitMqDTO(workflowNodeEntity.getCorpid(), Collections.singletonList(workflowTaskNodeEntity.getUserId()), Collections.singletonList(workflowTaskNodeEntity.getTaskId()), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_CARBON_COPY_TITLE), String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_CARBON_COPY_CONTENT), workflowTransferPOJO.getUser().getName(), formName, content), null, options);
                                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.APPROVAL_CARBON_COPY_PUSH);
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("com.xbongbong.workflow.service.strategy.node.AbstractWorkflowApprovalStrategy.post message fail", e);
                    }
                };
                threadPoolBeanConfig.dingtalkTodo().execute(runnable);

            }


        } catch (XbbException e) {
            log.error("com.xbongbong.workflow.service.strategy.node.AbstractWorkflowApprovalStrategy.createApprovalNode fail", e);
            throw new WorkflowException(e.getMsg());
        }


    }

    /**
     * Description: 无审批人处理
     * @param workflowTransferPOJO
	 * @param nodeEntity
	 * @param lastNodeId
     * @return boolean
     * @throws
     * @author 魏荣杰
     * @date 2021/8/23 16:39
     * @since
     */
    protected WorkflowNoApproverBo noApproverHandle(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, Long lastNodeId) throws WorkflowException {
        WorkflowNoApproverBo workflowNoApproverBo= new WorkflowNoApproverBo();
        Integer autoPaas = 0;
        // 审批人为空时，超管转交处理/自动通过/自动拒绝
        WorkflowEntity workflowEntity = workflowModel.getByKey(nodeEntity.getWorkflowId(), nodeEntity.getCorpid());
        Integer emptyApproverType = workflowEntity != null ? workflowEntity.getEmptyApproverType() : ProcessEmptyApproverTypeEnum.ADMIN_TRANSFER.getValue();
        if (Objects.equals(emptyApproverType, ProcessEmptyApproverTypeEnum.AUTO_PAAS.getValue())) {
            // TODO: 2021/5/24 跟老逻辑review对一下
            // 自动通过
            createApprovalNode(Collections.singletonList(PaasConstant.SYS_USER_ID), workflowTransferPOJO, nodeEntity, lastNodeId, TaskTypeEnum.COMMIT);
            autoPaas = 1;
        } else if (Objects.equals(emptyApproverType, ProcessEmptyApproverTypeEnum.AUTO_REJECT.getValue())) {
            // 自动拒绝
            createApprovalNode(Collections.singletonList(PaasConstant.SYS_USER_ID), workflowTransferPOJO, nodeEntity, lastNodeId, TaskTypeEnum.END);
            autoPaas = 2;
        } else {
            // 超管转交处理
            createApprovalNode(Collections.singletonList(PaasConstant.SYS_USER_ID), workflowTransferPOJO, nodeEntity, lastNodeId, TaskTypeEnum.SYSTEM_COMMIT);
        }
        workflowNoApproverBo.setAutoPaas(autoPaas);
        return workflowNoApproverBo;
    }
    /**
     *
     */
    /**
     * Description: 创建钉钉待办任务
     * @param workflowTaskNodeEntityList
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2022/1/6 18:02
     * @since
     */
    protected void createDingtalkTodoTask(List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList) {
        workflowApprovalOperate.createDingtalkTodoTask(workflowTaskNodeEntityList);
    }

    /**
     * Description: 判断是不是审批开始节点
     * @param workflowTaskNodeEntity
     * @return boolean
     * @throws
     * @author 魏荣杰
     * @date 2021/5/24 10:48
     * @since
     */
    protected boolean isCreateTaskNode(WorkflowTaskNodeEntity workflowTaskNodeEntity) {
        return WorkflowTaskUtil.isCreateTaskNode(workflowTaskNodeEntity);
    }

    /**
     * Description: 判断是不是审批的节点
     * @param workflowTaskNodeEntity
     * @return boolean
     * @throws
     * @author 魏荣杰
     * @date 2021/5/24 10:50
     * @since
     */
    protected boolean isApprovalNode(WorkflowTaskNodeEntity workflowTaskNodeEntity) {
        return (Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.COMMIT.getType()) || Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.SYSTEM_PASS.getType()) || Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.UNTREATED.getType()) || Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.COMMIT_PRINT.getType()))
                && Objects.equals(workflowTaskNodeEntity.getNodeType(), NodeTypeEnum.PROCESS_NODE.getNodeType());
    }

    /**
     * 创建钉钉待办
     * @param workflowTransferPOJO
     */
    protected void createDingtalkInstance(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity, Long insert) {

        try {
            String corpid = workflowNodeEntity.getCorpid();
            Long formId = workflowNodeEntity.getFormId();
            Integer saasMark = workflowNodeEntity.getSaasMark();

            // 获取 dingtalkProcessCode
            String dingtalkProcessCode = workflowDingtalkService.getDingtalkProcessCode(corpid);
            if (StringUtil.isEmpty(dingtalkProcessCode)) {
                return;
            }

            // 表单名称
            String formName;
            // 内容提要
            String customTitle;
            List<FieldAttrEntity> explainList;
            if (Objects.equals(workflowNodeEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                //表单
                WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(formId, corpid);
                if (workOrderFormEntity == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                formName = workOrderFormEntity.getName();
                customTitle = workOrderFormEntity.getCustomTitle();
                //解释
                WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(workOrderExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                explainList = JSONArray.parseArray(workOrderExplainEntity.getExplains(), FieldAttrEntity.class);
            } else {
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
                if (paasFormEntityExt == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                formName = paasFormEntityExt.getName();
                customTitle = paasFormEntityExt.getCustomTitle();

                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            }
            JSONArray titleArray = JSONArray.parseArray(customTitle);
//            JSONArray attrArray = new JSONArray();
//            for (Object obj : titleArray) {
//                JSONObject attrJson = (JSONObject) obj;
//                String attr = attrJson.getString("attr");
//                attrArray.add(attr);
//            }
            List<String> attrArray = titleArray.stream().map(t -> (JSONObject) t).map(t -> t.getString("attr")).collect(Collectors.toList());

            Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
            if(CollectionsUtil.isNotEmpty(explainList)){
//                for(FieldAttrEntity fieldAttrEntity : explainList) {
//                    if (attrArray.contains(fieldAttrEntity.getAttr())) {
//                        explainMap.put(fieldAttrEntity.getAttr(), fieldAttrEntity);
//                    }
//                }
                explainMap = explainList.stream().filter(t -> attrArray.contains(t.getAttr())).collect(Collectors.toMap(FieldAttrEntity::getAttr, t -> t));
            }

            // 此处因为复用getDataList()和getSpecialDataList()方法，所以新建一个PaasFormDataEntityExt对象(不要去查询实体，因为还在审批中，查不到)，该对象目前用了addTime,updateTime,serialNo三个值
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            // 还是做一遍查询吧
//            PaasProcessDataEntity processData = paasProcessDataModel.getByTaskId(workflowTransferPOJO.getTaskId(), corpid);

            //查询主表数据
            List<PaasFormDataEntityExt> dataIdList = formDataHelp.getByDataIdList(
                    Sets.newHashSet(workflowTransferPOJO.getData().getId()),
                    workflowNodeEntity.getBusinessType(),
                    workflowNodeEntity.getSaasMark(), workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
            workflowHelp.checkQueryResult(dataIdList);
            PaasFormDataEntityExt processData = dataIdList.get(0);

            BeanUtil.copyProperties(processData, paasFormDataEntityExt);
            // data 要进行处理，不然复用 ExplainUtil 中的方法会报错 (此处坑很多，目前只能遇一个改一个)
            JSONObject data = processData.getData();
            // ownerId , coUserId, createId
            List<String> userIdList = new ArrayList<>();
            if (data.containsKey(FieldTypeEnum.OWNERID.getAlias())) {
                List<String> ownerIds = data.getJSONArray("ownerId").toJavaList(String.class);
                userIdList.addAll(ownerIds);
            }
            if (data.containsKey(FieldTypeEnum.COUSERID.getAlias())) {
                List<String> coUserIds = data.getJSONArray("coUserId").toJavaList(String.class);
                userIdList.addAll(coUserIds);
            }
            userIdList.add(processData.getCreatorId());
            List<UserEntity> userEntities = userModel.getByUserIdIn(corpid, userIdList, false);
            workflowHelp.checkQueryResult(userEntities);
            Map<String, UserEntity> userMap = userEntities.stream().collect(Collectors.toMap(UserEntity::getUserId, t -> t));

            // 解析标题
            List<FormTitlePoJo> formTitleList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                if (data.containsKey(FieldTypeEnum.OWNERID.getAlias())) {
                    List<ReturnUserAndDepartmentPojo> pojoList = new ArrayList<>();
                    JSONArray jsonArray = data.getJSONArray("ownerId");
                    for (Object o : jsonArray) {
                        ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = new ReturnUserAndDepartmentPojo();
                        BeanUtil.copyProperties(userMap.get(o.toString()), returnUserAndDepartmentPojo);
                        pojoList.add(returnUserAndDepartmentPojo);
                    }
                    data.put(FieldTypeEnum.OWNERID.getAlias(), pojoList);
                }
                if (data.containsKey(FieldTypeEnum.COUSERID.getAlias())) {
                    List<ReturnUserAndDepartmentPojo> pojoList = new ArrayList<>();
                    JSONArray jsonArray = data.getJSONArray("coUserId");
                    for (Object o : jsonArray) {
                        ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = new ReturnUserAndDepartmentPojo();
                        BeanUtil.copyProperties(userMap.get(o.toString()), returnUserAndDepartmentPojo);
                        pojoList.add(returnUserAndDepartmentPojo);
                    }
                    data.put(FieldTypeEnum.COUSERID.getAlias(), pojoList);
                }
                // 创建人
                UserEntity creatorUser = userMap.get(processData.getCreatorId());
                data.put(FieldTypeEnum.CREATORID.getAlias(), Objects.nonNull(creatorUser) ? creatorUser.getName() : "");
                formTitleList = ExplainUtil.getSpecailFormTitle(titleArray, explainMap, data, explainList, paasFormDataEntityExt);

            } else if (Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
                if (data.containsKey(FieldTypeEnum.OWNERID.getAlias())) {
                    if (!data.getJSONArray("ownerId").isEmpty()) {
                        data.put(FieldTypeEnum.OWNERID.getAlias(), userMap.get(data.getJSONArray("ownerId").get(0).toString()).getName());
                    }
                }
                UserEntity creatorUser = userMap.get(processData.getCreatorId());
                data.put(FieldTypeEnum.CREATORID.getAlias(), Objects.nonNull(creatorUser) ? creatorUser.getName() : "");
                formTitleList = ExplainUtil.getFormTitle(titleArray, explainMap, data, explainList, paasFormDataEntityExt);
            }
            // 拼接summaryTitle
            StringBuilder summaryTitle = new StringBuilder();
            for (FormTitlePoJo item : formTitleList) {
                if (StringUtil.isEmpty(item.getAttr())) {
                    summaryTitle.append(item.getContent()).append(" ");
                } else {
                    for (Object object : item.getValue()) {
                        summaryTitle.append(object.toString()).append(" ");
                    }
                }
            }
            // 复用OA消息的 options
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(), formId, null,
                    saasMark, workflowNodeEntity.getBusinessType(), workflowTransferPOJO.getTaskId(), insert, ProcessTypeEnum.CREATE.getValue());
            // formName: 表单名称， userId：表单提交人id， userName:表单提交人姓名， submitTime: 提交时间 options：复用OA消息的 options
            UserEntity creatorUser = userModel.getByKeyIngoreDel(workflowTransferPOJO.getUser().getUserId(), corpid);
            // 防空指针
            if (Objects.nonNull(creatorUser)){
                WorkrecordInstanceDTO workrecordInstanceDTO = new WorkrecordInstanceDTO(corpid, dingtalkProcessCode, formName,
                        summaryTitle.toString(), workflowTransferPOJO.getUser().getUserId(), creatorUser.getName(), DateUtil.getInt(), options);
                workflowDingtalkService.createDingtalkInstance(workrecordInstanceDTO);
            }
        } catch (Exception e) {
            log.error("创建钉钉待办实例失败", e);
        }
    }

    /**
     * Description: 无需审批人判断,true为无需审批人
     * @param user
	 * @param rolesWithoutApprove
     * @param corpid
     * @return boolean
     * @throws
     * @author 魏荣杰
     * @date 2021/9/3 15:23
     * @since
     */
    protected boolean isNoNeedApproval(User user, String rolesWithoutApprove, String corpid) {
        List<OptionalRangeEntity> optionalRangeEntities = JSON.parseArray(rolesWithoutApprove, OptionalRangeEntity.class);
        Set<String> roles = new HashSet<>();
        Set<String> departmantIds = new HashSet<>();
        Set<String> userIds = new HashSet<>();
        for (OptionalRangeEntity optionalRangeEntity : optionalRangeEntities) {
            if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.DEPT.getValue())) {
                departmantIds.add(optionalRangeEntity.getId());
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.ROLE.getValue())) {
                roles.add(optionalRangeEntity.getId());
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.USER.getValue())) {
                userIds.add(optionalRangeEntity.getId());
            }
        }

        UserVO userVO = userModel.getUserVoRoleAndDepartment(corpid, user.getUserId());
        Set<RoleSimpleVO> roleSet = userVO.getRoleSet();
        Set<DepartmentVO> depSet = userVO.getDepSet();
        if (CollectionsUtil.isNotEmpty(userIds)) {
            if (userIds.contains(user.getUserId())) {
                return true;
            }
        }
        if (CollectionsUtil.isNotEmpty(roleSet)) {
            for (RoleSimpleVO roleSimpleVO : roleSet) {
                if (roles.contains(roleSimpleVO.getId().toString())) {
                    return true;
                }
            }
        }
        if (CollectionsUtil.isNotEmpty(depSet)) {
            for (DepartmentVO departmentVO : depSet) {
                if (departmantIds.contains(departmentVO.getId().toString())) {
                    return true;
                }
            }
        }
        return false;
    }
}
